package eg.sample;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.Color.*;
import java.util.*;
import java.util.regex.*;//split strings
import javax.swing.border.*;//allows the use of borders

public class CaesarCipher extends JFrame {
	private static JTextField inputKeyTF;

	private static JTextArea outputTA, inputTA;

	private JLabel headingL, encryptKeyL;

	private JScrollPane scrollText, scrollText2, scrollText3;// creates the
																// scroll
																// feature for
																// JTextArea

	private JButton encryptB, decryptB, exitB, clearB;

	private EncryptButtonHandler encrbHandler;
	private DecryptButtonHandler decryptHandler;
	private ExitButtonHandler ebHandler;
	private ClearButtonHandler clbHandler;

	private static int WIDTH = 1035;
	private static int HEIGHT = 530;

	public CaesarCipher() {
		/************************************************************* Create borders **/
		Border raisedbevel, loweredbevel, blackline, compound;
		blackline = BorderFactory.createLineBorder(Color.black);
		raisedbevel = BorderFactory.createRaisedBevelBorder();
		loweredbevel = BorderFactory.createLoweredBevelBorder();
		compound = BorderFactory.createCompoundBorder(loweredbevel, blackline);
		/************************************************************* Create Fonts **/
		Font font = new Font("Courier New", Font.BOLD, 30);
		Font font2 = new Font("Times New Roman", Font.BOLD, 30);
		Font font3 = new Font("Times New Roman", Font.BOLD, 26);
		/************************************************************* Create labels **/
		headingL = new JLabel("Enter your text below and a shift key,"
				+ " then click Encrypt or Decrypt", SwingConstants.CENTER);
		encryptKeyL = new JLabel("Enter a key between -25 and 25:");

		inputTA = new JTextArea("", 50, 895);
		/*************** SET GRAY BACKGROUND IMAGE IN TEXT AREA ***************/
		final ImageIcon imageIcon = new ImageIcon("Caesar_cipher.png");
		inputTA = new JTextArea("", 50, 895) {
			Image image = imageIcon.getImage();

			Image grayImage = GrayFilter.createDisabledImage(image);
			{
				setOpaque(false);
			}

			public void paint(Graphics g) {
				g.drawImage(grayImage, 0, 0, this);
				super.paint(g);
			}
		};// END SET BACKGROUND IMAGE
		inputTA.setFont(font);
		scrollText2 = new JScrollPane(inputTA);// adds the scroll feature to the
												// outputTA
		scrollText2
				.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
		inputTA.setLineWrap(true);
		inputTA.setWrapStyleWord(true);

		inputKeyTF = new JTextField(3);
		inputKeyTF.setFont(font);

		outputTA = new JTextArea("", 50, 895);
		outputTA.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
		/*************** SET GRAY BACKGROUND IMAGE IN TEXT AREA ***************/
		final ImageIcon imageIcon2 = new ImageIcon("encrypted.png");
		outputTA = new JTextArea("", 50, 895) {
			Image image = imageIcon2.getImage();

			Image grayImage = GrayFilter.createDisabledImage(image);
			{
				setOpaque(false);
			}

			public void paint(Graphics g) {
				g.drawImage(grayImage, 0, 0, this);
				super.paint(g);
			}
		};// END SET BACKGROUND IMAGE

		outputTA.setFont(font);

		scrollText = new JScrollPane(outputTA);// adds the scroll feature to the
												// outputTA
		scrollText
				.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
		outputTA.setLineWrap(true);
		outputTA.setWrapStyleWord(false);
		outputTA.setEditable(false);

		encryptB = new JButton("Encrypt");
		encrbHandler = new EncryptButtonHandler();
		encryptB.addActionListener(encrbHandler);
		encryptB.setFont(font2);

		decryptB = new JButton("Decrypt");
		decryptHandler = new DecryptButtonHandler();
		decryptB.addActionListener(decryptHandler);
		decryptB.setFont(font2);

		exitB = new JButton("EXIT");
		ebHandler = new ExitButtonHandler();
		exitB.addActionListener(ebHandler);
		exitB.setFont(font2);

		clearB = new JButton("Clear All");
		clbHandler = new ClearButtonHandler();
		clearB.addActionListener(clbHandler);
		clearB.setFont(font2);

		setTitle("The Caesar Cipher");

		Container myWindow = getContentPane();
		myWindow.setLayout(null);

		decryptB.setLocation(750, 232);
		encryptB.setLocation(540, 232);
		exitB.setLocation(525, 453);
		clearB.setLocation(250, 453);

		scrollText2.setLocation(5, 52);
		inputKeyTF.setLocation(465, 233);
		scrollText.setLocation(5, 273);

		decryptB.setSize(200, 40);
		encryptB.setSize(200, 40);
		exitB.setSize(225, 40);
		clearB.setSize(225, 40);

		headingL.setSize(1010, 40);
		headingL.setLocation(5, 5);
		headingL.setFont(font2);
		encryptKeyL.setSize(430, 40);
		encryptKeyL.setLocation(50, 233);
		encryptKeyL.setFont(font2);

		scrollText2.setSize(1010, 180);
		inputKeyTF.setSize(60, 40);
		scrollText.setSize(1010, 180);
		scrollText.setBorder(compound);
		scrollText2.setBorder(compound);

		myWindow.add(decryptB);
		myWindow.add(encryptB);
		myWindow.add(exitB);
		myWindow.add(clearB);
		myWindow.add(headingL);
		myWindow.add(encryptKeyL);
		myWindow.add(scrollText2);
		myWindow.add(inputKeyTF);
		myWindow.add(scrollText);

		setSize(WIDTH, HEIGHT);
		setVisible(true);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
	}

	private class EncryptButtonHandler implements ActionListener {// start
																	// encrypt
																	// button
																	// class
		public void actionPerformed(ActionEvent e) {
			String sentence;
			int key;

			sentence = inputTA.getText();
			sentence = sentence.toLowerCase();
			sentence = sentence.replaceAll("[^a-zA-Z]+", "");// removes all
																// special
																// characters
																// and numbers
																// from the
																// user's input
																// to make
																// encryption
																// harder to
																// hack
																// --To leave
																// spaces
																// between the
																// words
																// just leave a
																// space after
																// A-Z
			try {
				key = Integer.parseInt(inputKeyTF.getText());
				outputTA.setForeground(Color.blue);
				outputTA.setText("");

				if ((key >= -25) && (key <= 25)) {
					char[] chars = sentence.toCharArray();

					for (int i = 0; i < sentence.length(); i++) {
						char c = chars[i];
						char encrypted = encrypt(c, key);
						String output = Character.toString(encrypted);

						/*****
						 * The output could have been simply output by using the
						 * string. The same way the DecryptButtonHandler output
						 * the text, but I was just practicing with arrays so I
						 * did it as follows:
						 ****/
						output.split("\\s");
						String[] outputArray = { output };

						for (int index = 0; index < outputArray.length; index++) {// NESTED
																					// FOR
																					// LOOP
							outputTA.append(outputArray[index]);// ENCRYPTED
																// INPUT IS
																// DISPLAYED
																// HERE
						}// end inside FOR LOOP
					}// end outside FOR LOOP
				}

				else {
					outputTA.setForeground(Color.red);
					outputTA.setText("Key must be between -25 and 25!");
					inputKeyTF.setText("");
					inputKeyTF.requestFocusInWindow();

					key = Integer.parseInt(inputKeyTF.getText());

				}
			}// end try
			catch (NumberFormatException h) {
				outputTA.setForeground(Color.red);
				outputTA.setText("Please enter a number between -25 and 25.");
				inputKeyTF.requestFocusInWindow();
			} catch (Exception j) {
				outputTA.setForeground(Color.red);
				outputTA.setText("Please enter a number between -25 and 25.");
				inputKeyTF.requestFocusInWindow();
			}
		}
	}// END EncryptButtonHandler

	public static char encrypt(char c, int key)/***** encrypt Method ******/
	{
		char[] alphabet = new char[26];
		int i = 0;

		for (char ch = 'a'; ch <= 'z'; ++ch)// fills alphabet array with the
											// alphabet
		{
			alphabet[ch - 'a'] = ch;
		}

		/********************** BELOW CODE FROM: ***********************/
		// http://www.cs.utsa.edu/~wagner/laws/Acaesar.html

		while (i < 26) {
			if (c == alphabet[i])
				return alphabet[(i + key + 26) % 26];
			i++;
		}
		return c;
		/*************************************************************/
	}

	private class DecryptButtonHandler implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			String sentence;
			int key;

			sentence = inputTA.getText();

			try {
				key = Integer.parseInt(inputKeyTF.getText());

				outputTA.setForeground(Color.blue);
				outputTA.setText("");

				if ((key >= -25) && (key <= 25)) {
					char[] chars = sentence.toCharArray();

					for (int i = 0; i < sentence.length(); i++) {
						char c = chars[i];
						char decrypted = decrypt(c, key);
						String output = Character.toString(decrypted);

						outputTA.append(output);// Decrypted Output
					}
				} else {
					outputTA.setForeground(Color.red);
					outputTA.setText("Key must be between -25 and 25!");
					inputKeyTF.setText("");
					inputKeyTF.requestFocusInWindow();

					key = Integer.parseInt(inputKeyTF.getText());

				}
			}// end try
			catch (NumberFormatException h) {
				outputTA.setForeground(Color.red);
				outputTA.setText("Please enter a number between -25 and 25.");
				inputKeyTF.requestFocusInWindow();
			} catch (Exception j) {
				outputTA.setForeground(Color.red);
				outputTA.setText("Please enter a number between -25 and 25.");
				inputKeyTF.requestFocusInWindow();
			}
		}
	}// END DecryptButtonHandler

	public static char decrypt(char c, int key)/******* decrypt Method ************/
	{
		char[] alphabet = new char[26];
		int i = 0;

		for (char ch = 'a'; ch <= 'z'; ++ch) {
			alphabet[ch - 'a'] = ch;// fills the array with the alphabet
		}

		/********************** BELOW CODE FROM: ***********************/
		// http://www.cs.utsa.edu/~wagner/laws/Acaesar.html

		while (i < 26) {
			if (c == alphabet[i])
				return alphabet[(i - key + 26) % 26];
			i++;
		}
		return c;
	}

	/*************************************************************/

	private class ExitButtonHandler implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			System.exit(0);// allows the exit button to close the JFrame window
		}
	}// End of EXIT BUTTON actionPerformed

	private class ClearButtonHandler implements ActionListener {
		public void actionPerformed(ActionEvent e) {
			inputTA.setText("");
			outputTA.setText("");

			inputKeyTF.setText("");
			inputTA.requestFocusInWindow();
		}
	}

	public static void main(String[] args) {

		CaesarCipher cipherObject = new CaesarCipher();
		cipherObject.setLocationRelativeTo(null);// lets the window popup in the
													// middle of the user's
													// screen
	}
}
// END OF CODE
